﻿using Microsoft.AspNet.SignalR.Client;
using System;
using System.Threading.Tasks;

namespace AisinGioro.WinAgent
{
    using Core;
    using Core.DTOs;

    public class ClientManager
    {
        string _hostUrl;
        HubConnection _hubConn;
        IHubProxy _msgProxy;

        public string HostUrl { get { return _hostUrl; } }

        public event EventHandler OnStartSucceed;
        public event EventHandler OnStopSucceed;
        public event EventHandler<ErrorOccuredEventArgs> OnFailed;
        public Action<ConnectionState> StateChanged { get; set; }
        
        public ClientManager(string hostUrl)
        {
            _hostUrl = hostUrl;

            _hubConn = new HubConnection(_hostUrl, "role=agent");
            _hubConn.TransportConnectTimeout = new TimeSpan(0, 0, 10);
            _hubConn.StateChanged += HubConnStateChanged;
            _hubConn.TraceLevel = TraceLevels.All;
            _hubConn.TraceWriter = Console.Out;
            _msgProxy = _hubConn.CreateHubProxy("msgHub"); //实例化客户端代理
        }

        private void HubConnStateChanged(StateChange stateChange)
        {
            if (StateChanged != null)
                StateChanged(stateChange.NewState);
        }

        public async void Start()
        {
            try
            {
                if (_hubConn.State == ConnectionState.Disconnected)
                {
                    await _hubConn.Start();
                }
                
                if (this.OnStartSucceed != null)
                    this.OnStartSucceed(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                ex = ex.GetBaseException();
                LogHelper.Error(ex.Message + " " + _hostUrl);

                if (this.OnFailed != null)
                    this.OnFailed(this, new ErrorOccuredEventArgs(ex));
            }
        }

        public void Stop()
        {
            if (_hubConn != null && _hubConn.State != ConnectionState.Disconnected)
            {
                _hubConn.Stop();
            }
                        
            if (this.OnStopSucceed != null)
                this.OnStopSucceed(this, EventArgs.Empty);
        }

        /// <summary>
        /// 上传系统信息
        /// </summary>
        public async Task SubmitSysInfo(BaseHostDto dto)
        {            
            if (_hubConn.State == ConnectionState.Connected)
            {
                string methodName = "Unknown";
                try
                {
                    if (dto is HeartbeatDto)
                        methodName = "pushHeartbeat";
                    else if (dto is CPUInfoDto)
                        methodName = "pushCPU";
                    else if (dto is DiskInfoDto)
                        methodName = "pushDisk";
                    else if (dto is MemoryInfoDto)
                        methodName = "pushMemory";
                    else if (dto is CurrentConnectionDto)
                        methodName = "pushCurrentConnection";
                    else
                        throw new Exception("Invalid dto.");

                    await _msgProxy.Invoke(methodName, dto);
                    LogHelper.Info("{0} => {1}", methodName, _hubConn.JsonSerializeObject(dto));
                }
                catch (Exception ex)
                {
                    LogHelper.Error("{0} => {1}. Delay 10 seconds", methodName, ex.Message);
                    await Task.Delay(10000);  //发生错误延迟10秒
                }
            }
        }
    }
}
